#include "Pipe.h"

DWORD ThrPipeThreadRead(void *www) {
	Pipe * pipe = (Pipe *)www;
	pipe->loop();
	return 0;
	//创建内核对象使用完之后一定记得关闭，有可能会产生内存泄露
}
DWORD WaitPipe(void *www) {
	Pipe * pipe = (Pipe *)www;
	pipe->isloop();
	return 0;
}


Pipe::Pipe( char * com) {
	this->setHwnd();
	ai.nLength = sizeof(SECURITY_ATTRIBUTES);
	ai.bInheritHandle = true;
	ai.lpSecurityDescriptor = NULL;
	if (!CreatePipe(&hpiperead, &hpipewrite, &ai, 0)) { //创建读入管道

		this->setStatus(-1, "[0x01]Read 流创建失效");
		return;
	}

	if (!CreatePipe(&hpiperead2, &hpipewrite2, &ai, 0)) { //创建读入管道

		this->setStatus(-1, "[0x02]Write 流创建失效");
		return;
	}
	GetStartupInfoA(&si);    //获取当前进程的STARTUPINFO
	si.cb = sizeof(STARTUPINFO);
	si.hStdError = hpipewrite;
	si.hStdOutput = hpipewrite;
	si.hStdInput = hpiperead2;
	si.wShowWindow = SW_SHOW;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

	if (!(CreateProcessA(NULL, com, NULL, NULL, true, NULL, NULL, NULL, &si, &pi))) {    //创建隐藏的CMD进程
		this->setStatus(-1, "[0x03] CreateProcess函数执行出错");
		return;
	}


	DWORD dwThread = FALSE;
	hThrLoop = CreateThread(NULL, 0, ThrPipeThreadRead, this, 0, &dwThread);//chuangjian
	if (hThrLoop == FALSE) {
		this->setStatus(-1, "[0x11] 线程创建失败 CreateThread LOOP 失败");
		return;
	}
	hThrLoop = CreateThread(NULL, 0, WaitPipe, this, 0, &dwThread);//chuangjian
	if (hThrLoop == FALSE) {
		this->setStatus(-1, "[0x12] 线程创建失败 CreateThread ISLOOP失败");
		return;
	}
}




Pipe::~Pipe() {
	//创建内核对象使用完之后一定记得关闭，有可能会产生内存泄露
	this->setPipeOn(false);
	this->setStatus(-1);
	CloseHandle(hThrisLoop);
	CloseHandle(hThrLoop);
	CloseHandle(hpipewrite);
	CloseHandle(hpiperead);
	CloseHandle(hpiperead2);
	CloseHandle(hpipewrite2);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

}
const INT Pipe::getStatus() const {
	return this->status;
}

const string & Pipe::getError() const {
	return this->errorString;
}

const BOOL Pipe::isPipeOff() const {
	return pipe;
}

void Pipe::setPipeOn(const BOOL bools) {
	this->pipe = bools;
}

void Pipe::setStatus(const INT status, const char * info) {
	this->errorString = info;    //你说会不会有更好的赋值方法?
	this->status = status;
}

void Pipe::setStatus(const INT status = 1) {
	this->status = status;
}

const BOOL Pipe::sendCommand(const char * com) {   //执行命令
	DWORD dwWrite = 0;
	char www[1024];
	strcpy_s(www,com);
	strcat_s(www,"\n");
	return WriteFile(hpipewrite2, www, strlen(www), &dwWrite, NULL);
	//0x001C7796 处有未经处理的异常(在 ConsoleApplication2.exe 中):  0xC0000005:  读取位置 0x0000000C 时发生访问冲突。
}

void Pipe::loop() {
	//char outbuff[4096];        //输出缓冲
	DWORD byteread;
	this->setPipeOn(true);
	while (true) {
		memset(this->outbuff, '\0', 4096);
		if (ReadFile(this->hpiperead, this->outbuff, 4095, &byteread, NULL) == NULL) {
			this->setPipeOn(false);
			break;
		}
		printf("%s", this->outbuff);
		this->test();
		memset(outbuff, '\0', 4096);
	}
	this->setPipeOn(false);
	std::cout << "Pipe Stoped!"<<endl;
}

void Pipe::isloop() {
	DWORD dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
	while (dwRet == WAIT_TIMEOUT) {
		dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
	}

	if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED) {
		this->setPipeOn(false);
		std::cout << "[END] Pipe Stoped!" << endl;
	}
}

string getBuff(Pipe *pipe) {
	return pipe->outbuff;
}

void Pipe::test() {


	Json::Reader reader;
	Json::Value root;
	std::string name;
	int id = 0;
	string test=this->outbuff;
	cout<<"test........."<<test<<endl;
	string test1="code";
	string::size_type idx=test.find(test1); //在a中查找b.
	if (!(idx == string::npos) ) {
		if(reader.parse(this->outbuff,root)) {
			string	code = root["code"].asString();
			HWND hd=	FindWindowA("myclass","title");
			HDC         hdc;
			PAINTSTRUCT ps;
			hdc = BeginPaint(hd, &ps);
			if(code=="100") {
				cout<<code<<endl;
				const Json::Value data=root["data"];
				for (int i=0; i<data.size(); i++) {
					int x1=data[i]["box"][0][0].asInt();
					int y1=data[i]["box"][0][1].asInt();
					int x2=data[i]["box"][4][0].asInt();
					int y2=data[i]["box"][4][1].asInt();
						Rectangle(hdc, x1, y1, x2, y2);
				}
			}
			//            HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));         //2
			//			HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);      //3
			//			Rectangle(hdc, 50, 50, 200, 200);                         //4
			//			SelectObject(hdc, hOldBrush);                             //5
			//			DeleteObject(hBrush);
			EndPaint(hd, &ps);
			::UpdateWindow( hd );
		}

	}
}

void Pipe::setHwnd() {

	this->hwnd=FindWindowA("myclass","title");

}